package com.cj.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cj.common.constant.Constant;
import com.cj.common.exception.BaseException;
import com.cj.common.response.Result;
import com.cj.common.utils.DateUtil;
import com.cj.common.utils.StrUtil;
import com.cj.user.dao.FileMapper;
import com.cj.user.entity.File;
import com.cj.user.service.FileFeignService;
import com.cj.user.service.FileService;
import com.cj.user.service.RabbitMqFeignService;
import feign.Response;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author cheng jun
 * @Description:
 * @Date 2021/7/9 21:55
 */
@Service
public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements FileService {

    @Resource
    private FileFeignService fileFeignService;
    @Resource
    private RabbitMqFeignService rabbitMqFeignService;

    @Override
    public boolean saveFile(MultipartFile file, String fileId) {
        // 调用文件服务来上传
        Result<File> upload = fileFeignService.upload(file);
        if (0 != upload.getCode()) {
            throw new BaseException("openFeign调用失败");
        }

        // 存储文件信息
        File fileResult = new File();
        fileResult.setId(StrUtil.getUuid32());
        fileResult.setFileId(fileId);
        Date date = DateUtil.getCurrentDate();
        fileResult.setCreationTime(date);
        fileResult.setUpdateTime(date);
        fileResult.setExtension(upload.getData().getExtension());
        fileResult.setNewName(upload.getData().getNewName());
        fileResult.setOriginalName(upload.getData().getOriginalName());
        fileResult.setPath(upload.getData().getPath());
        fileResult.setSize(upload.getData().getSize());
        fileResult.setType(upload.getData().getType());
        boolean flag = this.save(fileResult);

        // 通知mq下订单,topics模型（不用管是否成功发送消息）
        Map<String, Object> mqMap = new HashMap<>();
        mqMap.put("orderId", fileId);
        mqMap.put("orderName", upload.getData().getOriginalName());
        mqMap.put("creationTime", DateUtil.dateConvetStr(date));
        rabbitMqFeignService.topics(mqMap);

        return flag;
    }

    @Override
    public void selectFile(Map<String, Object> map, HttpServletResponse response) {
        // 参数校验
        Assert.notNull(map.get("fileId"), "文件id不能为空");
        Assert.notNull(map.get("openStyle"), "打开方式不能为空");

        // 获取文件信息
        QueryWrapper<File> queryWrapper = new QueryWrapper();
        queryWrapper.select("new_name", "path", "original_name");
        queryWrapper.eq("file_id", String.valueOf(map.get("fileId")));
        File file = this.getOne(queryWrapper);

        // 封装参数
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("path", file.getPath());
        paramMap.put("newName", file.getNewName());
        paramMap.put("original_name", file.getOriginalName());

        // 文件下载
        this.downLoad(paramMap, response);
    }

    public void downLoad(Map<String, Object> map, HttpServletResponse response) {
        InputStream inputStream = null;
        ServletOutputStream servletOutputStream = null;
        try {
            // 调用文件服务来下载
            Response serviceResponse = fileFeignService.download(map, response);
            Response.Body body = serviceResponse.body();
            inputStream = body.asInputStream();

            // 设置下载名(attachment:下载，inline：在线打开)
            response.setHeader("content-disposition", map.get("openStyle") + ";fileName=" +
                    URLEncoder.encode(String.valueOf(map.get("original_name")), Constant.UTF_8));
            // 获取响应输出流
            servletOutputStream = response.getOutputStream();

            // 第四种方式：文件拷贝
            IOUtils.copy(inputStream, servletOutputStream);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BaseException(e.getMessage());
        } finally {
            // 关闭输入输出流
            try {
                IOUtils.close(inputStream);
                IOUtils.close(servletOutputStream);
            } catch (IOException e) {
                log.error(e.getMessage());
                throw new BaseException(e.getMessage());
            }
        }
    }
}
